/*-
  use bamp::ApiParser;
  use bamp::CApiGen;

  my $api = bamp::ApiParser->new("../include/bamp/bamp.api", CLASSNAME);
  my $c   = bamp::CApiGen->new($api);
  die "API parsing failed" if ${$api}{errors};

  my $class      = CLASSNAME; $class =~ s/::/_/g;
  my $incl_guard = "__BAMP_".uc($class)."_H__";
  my $struct     = lc($class);
  my $shortname  = $struct;
  $shortname =~ s/\w+?_//;

  my @includes = (
  "bamp/rc.h",
  "bamp/${shortname}_api.h",
  "locale.h",
  "stdlib.h");
*/
/*
 * /*= $c->header() */
 */

/*- for ($api->includes("C", @includes)) { */
#include </*$_*/>
/*- } */

bamp_rc /*$struct*/_new(/*$struct*/** /*$shortname*/)
{
    BAMP_RC_ASSERT(/*$shortname*/ != NULL, INVALID_ARGUMENT);

    // Allocate the structure
    */*$shortname*/ = malloc(sizeof(/*$struct*/));
    BAMP_RC_ASSERT(*/*$shortname*/ != NULL, OUT_OF_MEMORY);

    // Initialize the structure
    (*/*$shortname*/)->__ctx   = NULL;
    (*/*$shortname*/)->__refs  = 1;
    (*/*$shortname*/)->__dctor = NULL;
    (*/*$shortname*/)->__clone = NULL;

    /*-
      for my $p ($api->parents()) {
      for my $m ($api->class_methods($p)) {
      $p =~ s/\w+:://;
      $p = lc($p);
    */
    (*/*$shortname*/)->f./*$p*/./*$c->meth_name($m)*/ = NULL;
    /*- } } */

    return BAMP_RC_OK;
}

bamp_rc /*$struct*/_ref(/*$struct*/* /*$shortname*/)
{
    BAMP_RC_ASSERT(/*$shortname*/ != NULL, INVALID_ARGUMENT);
    ++(/*$shortname*/->__refs);
    return BAMP_RC_OK;
}

bamp_rc /*$struct*/_unref(/*$struct*/* /*$shortname*/)
{
    BAMP_RC_ASSERT(/*$shortname*/ != NULL, INVALID_ARGUMENT);
    --(/*$shortname*/->__refs);

    // Destroy the whole object
    if (/*$shortname*/->__refs == 0)
    {
        if (/*$shortname*/->__ctx   != NULL &&
            /*$shortname*/->__dctor != NULL)
        {
            /*$shortname*/->__dctor(/*$shortname*/->__ctx);
        }
        free(/*$shortname*/);
    }

    return BAMP_RC_OK;
}

bamp_rc /*$struct*/_clone(void** dst, /*$struct*/* src)
{
    BAMP_RC_ASSERT(dst != NULL, INVALID_ARGUMENT);
    BAMP_RC_ASSERT(src != NULL, INVALID_ARGUMENT);
    BAMP_RC_ASSERT(src->__ctx   != NULL, INVALID_ARGUMENT);
    BAMP_RC_ASSERT(src->__clone != NULL, NOT_READY);
    return src->__clone(dst, src->__ctx);
}

/*-
  for my $parent ($api->parents(), CLASSNAME) {
  for my $m ($api->class_methods($parent)) {
  my $p = lc($parent);
  $p =~ s/\w+:://;
  my $f = "";
  $f = "$p." unless $parent eq CLASSNAME;
  my $n = $c->meth_name($m);
  my @a;
  push (@a, "const $struct* $shortname") if ${$m}{const};
  push (@a, "$struct* $shortname")       if !${$m}{const};
  push (@a, $c->args($m));

  my @arglist = ($shortname."->__ctx");
  push @arglist, ${$_}[0] for @{${$m}{args}};
*/
bamp_rc /*$struct*/_/*$n*/(/*+join(", ", @a)*/)
{
    BAMP_RC_ASSERT(/*$shortname*/ != NULL, INVALID_ARGUMENT);
    BAMP_RC_ASSERT(/*$shortname*/->f./*$f*//*$n*/ != NULL, NOT_READY);
    BAMP_RC_ASSERT(/*$shortname*/->__ctx != NULL, NOT_READY);
    /*- 
      for my $arg (${$m}{args}) {
      if (defined ${$arg}[1] && ${$arg}[1] eq "out") {
    */
    BAMP_RC_ASSERT(/*${$arg}[0]*/ != NULL, INVALID_ARGUMENT);
    /*- } } */

    return /*$shortname*/->f./*$f*//*$n*/(/*+ join(", ", @arglist) */);
}

/*- } } */
